package vlms.dao;

import java.sql.*;
import java.util.*;
import java.sql.Date;

import vlms.bean.Account;
import vlms.bean.Cart;
import vlms.bean.IssuedMovie;
import vlms.bean.Movie;
import vlms.bean.Person;
import vlms.exception.AccountException;
import vlms.exception.CartException;
import vlms.exception.IssuedmovieException;
import vlms.util.DateConvert;
import vlms.util.Encryption;
import vlms.util.JDBCConnectionDriver;


public class IssuedmovieDAO {
	
	static HashMap<Integer, IssuedMovie> listByIssuedId;
	static HashMap<Integer, LinkedList<IssuedMovie>> listByPersonId;
	static HashMap<Integer, LinkedList<IssuedMovie>> listByMovieId;

	//Static Method Starts
	private static void staticPopulateVO(IssuedMovie dto, ResultSet rs) throws SQLException {
		dto.setIssueid(rs.getInt("issueId"));
		
		dto.setPersonid(rs.getInt("personId"));
		dto.setMovieid(rs.getInt("movieId"));
		dto.setIssuedate(rs.getDate("issueDate"));
		dto.setIssuedstatus(rs.getString("issueStatus"));
		dto.setDuedate(rs.getDate("dueDate"));
		dto.setReturndate(rs.getDate("returnDate"));
		dto.setFine(rs.getInt("fine"));

	}
	
	private static void initializeList(Connection con)
	{		
		listByIssuedId=new HashMap<Integer, IssuedMovie>();
		listByPersonId=new HashMap<Integer, LinkedList<IssuedMovie>>();
		listByMovieId=new HashMap<Integer, LinkedList<IssuedMovie>>();
		try {
			PreparedStatement stmt = null;
			ResultSet rs = null;
			
			String SQL_STATEMENT = "Select issueId, personId, movieId, issueDate, issueStatus, dueDate, returnDate,fine from issuedmovie";
			stmt = con.prepareStatement(SQL_STATEMENT);
			rs = stmt.executeQuery();

			
			while (rs.next()) {
				IssuedMovie dto=new IssuedMovie();
				staticPopulateVO(dto, rs);		
				
				if(!listByPersonId.containsKey(dto.getPersonid())) {
					LinkedList<IssuedMovie> issueMovie = new LinkedList<IssuedMovie>();
					listByPersonId.put(dto.getPersonid(), issueMovie);
				}
				
				listByPersonId.get(dto.getPersonid()).add(dto);
				
				if(!listByMovieId.containsKey(dto.getMovieid())) {
					LinkedList<IssuedMovie> issueMovie = new LinkedList<IssuedMovie>();
					listByMovieId.put(dto.getMovieid(), issueMovie);
				}
				
				listByMovieId.get(dto.getMovieid()).add(dto);
				
				listByIssuedId.put(new Integer(dto.getIssueid()), dto);
			}				
		}			
		catch(SQLException se) {
		
			System.out.println("Exception "+se+ " occured in the system." +
							   " Failed to initialize the list.");
			
		}
	}
	
	static 
	{
		Connection con=null;
		try {
			/*
			try {
				//
				new JDBCConnectionDriver("com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/vlmsdb", "root", "root", 10);
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InstantiationException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			*/
			con = DriverManager.getConnection("jdbc:user_mysql:");
			initializeList(con);
			//con.close();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally
		{
			try {
				con.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	//Static Method Ends
	
	//Find fields which are updated after last read
	private HashMap<String,Object> findUpdatedFields(IssuedMovie newIssueMovieObj, IssuedMovie listIssuedMovieObject) {
		
		HashMap<String,Object> updatedFieldsHashMap = new HashMap<String,Object>(); 
		if(listIssuedMovieObject.getIssuedstatus()==null)
		{
			updatedFieldsHashMap.put("issuestatus", newIssueMovieObj.getIssuedstatus());
		}
		else if(!newIssueMovieObj.getIssuedstatus().equals(listIssuedMovieObject.getIssuedstatus())) {
			updatedFieldsHashMap.put("issuestatus", newIssueMovieObj.getIssuedstatus());
		}
		if(listIssuedMovieObject.getReturndate()==null)
		{
			updatedFieldsHashMap.put("returndate", DateConvert.convertUtilToSQLdate(newIssueMovieObj.getReturndate()));
		}
		else if(newIssueMovieObj.getReturndate().compareTo(listIssuedMovieObject.getReturndate()) !=0) {
			updatedFieldsHashMap.put("returndate", DateConvert.convertUtilToSQLdate(newIssueMovieObj.getReturndate()));
		}
 		
		
		return updatedFieldsHashMap;
		
	}

	public int delete(int issueId, Connection con)
			throws SQLException, IssuedmovieException {
		PreparedStatement ps = null;
		ps = con.prepareStatement("delete from ISSUEDMOVIE where issueId = ?");
		ps.setInt(1, issueId);
		int result=ps.executeUpdate();
		if(result <= 0)
		{
			throw new IssuedmovieException("No issued movie found in the system.");
		}
		IssuedMovie obj=listByIssuedId.get(issueId);
		listByIssuedId.remove(issueId);
		listByPersonId.get(obj.getPersonid()).remove(obj);
		listByMovieId.get(obj.getMovieid()).remove(obj);
		
		return result;

	}

	public int updateIssuedInfo(IssuedMovie issuedmovie,
			Connection con) throws IssuedmovieException, SQLException {
		
		PreparedStatement ps = null;
		//Account listAccountObject = listByPersonId.get(personId);
		IssuedMovie listIssuedMovieObj = listByIssuedId.get(issuedmovie.getIssueid()); 
		String fieldsValue = null;
		String sqlQuery;
		int rowsUpdated=0;
		if(listIssuedMovieObj != null) {
		
			HashMap<String,Object> updatedFieldsHashMap = findUpdatedFields(issuedmovie,listIssuedMovieObj);
			
			Set<String> keys = updatedFieldsHashMap.keySet();
			
			Iterator<String> it = keys.iterator();			
			
			while(it.hasNext()) {
				System.out.println("" + keys.toString());
				String value=it.next();
				if(fieldsValue != null) 
				
					fieldsValue += "," + value + " = '" + updatedFieldsHashMap.get(value) + "'";
				else
					fieldsValue = value + " = '" + updatedFieldsHashMap.get(value) + "'";
				
				if(fieldsValue != null) {
					System.out.println("fieldsvalue" + fieldsValue);
					sqlQuery = "update ISSUEDMOVIE set " + fieldsValue + " where issueId = ?";
					System.out.println(sqlQuery);
					ps = con.prepareStatement(sqlQuery);
					ps.setInt(1, issuedmovie.getIssueid());
					rowsUpdated = ps.executeUpdate();
				}
			}
		}
		else {
			sqlQuery = "update ISSUEDMOVIE set issueStatus = '"+ issuedmovie.getIssuedstatus() + "', returnDate = '"
						+ DateConvert.convertUtilToSQLdate(issuedmovie.getReturndate()) + "' WHERE issueId = ?";
			System.out.println(sqlQuery);
			ps = con.prepareStatement(sqlQuery);
			ps.setInt(1, issuedmovie.getIssueid());
			rowsUpdated = ps.executeUpdate();
			}
		
		    
			if(rowsUpdated <= 0) {
				throw new IssuedmovieException("No Issued Movie found in the system");
			}
			else {
				IssuedMovie tempIssuedMovieObj=listByIssuedId.get(issuedmovie.getIssueid());
				
				LinkedList<IssuedMovie> issueMovieList = new LinkedList<IssuedMovie>();
				issueMovieList=listByMovieId.get(tempIssuedMovieObj.getMovieid());
				issueMovieList.remove(tempIssuedMovieObj);
				
				if(!listByMovieId.containsKey(issuedmovie.getMovieid())) {
					LinkedList<IssuedMovie> list = new LinkedList<IssuedMovie>();
					issueMovieList.add(issuedmovie);
					listByMovieId.put(issuedmovie.getMovieid(),list);
				}
				else
				{
					listByMovieId.get(issuedmovie.getMovieid()).add(issuedmovie);
				}
				
				LinkedList<IssuedMovie> issueMovieList1 = new LinkedList<IssuedMovie>();
				issueMovieList1=listByPersonId.get(tempIssuedMovieObj.getPersonid());
				issueMovieList1.remove(tempIssuedMovieObj);
				
				if(!listByMovieId.containsKey(issuedmovie.getPersonid())) {
					LinkedList<IssuedMovie> list = new LinkedList<IssuedMovie>();
					issueMovieList1.add(issuedmovie);
					listByPersonId.put(issuedmovie.getPersonid(),list);
				}
				else
				{
					listByPersonId.get(issuedmovie.getPersonid()).add(issuedmovie);
				}
				
				listByIssuedId.remove(issuedmovie.getIssueid());
				listByIssuedId.put(issuedmovie.getIssueid(), issuedmovie);
				
			}
		
			return (rowsUpdated);
	}
	
	public int updateFine(IssuedMovie issuedmovie,
			Connection con) throws IssuedmovieException, SQLException {
		
		
		
		
			PreparedStatement ps = null;
		
			IssuedMovie issuedMovieObj=listByIssuedId.get(issuedmovie.getIssueid());
			if(issuedMovieObj!=null)
			{
				int fine=issuedmovie.getFine();
				if(fine!=issuedMovieObj.getFine())
				{
					ps = con.prepareStatement("update ISSUEDMOVIE set FINE = ?  where issueId = ?");
					ps.setInt(1, issuedmovie.getFine());
					ps.setInt(2, issuedmovie.getIssueid());
					int result=ps.executeUpdate();
					if(result <= 0)
					{
						throw new IssuedmovieException("No issued movie found in the system.");
					}
					IssuedMovie tempIssuedMovieObj=listByIssuedId.get(issuedmovie.getIssueid());
					
					LinkedList<IssuedMovie> issueMovieList = new LinkedList<IssuedMovie>();
					issueMovieList=listByMovieId.get(tempIssuedMovieObj.getMovieid());
					issueMovieList.remove(tempIssuedMovieObj);
					
					if(!listByMovieId.containsKey(issuedmovie.getMovieid())) {
						LinkedList<IssuedMovie> list = new LinkedList<IssuedMovie>();
						issueMovieList.add(issuedmovie);
						listByMovieId.put(issuedmovie.getMovieid(),list);
					}
					else
					{
						listByMovieId.get(issuedmovie.getMovieid()).add(issuedmovie);
					}
					
					LinkedList<IssuedMovie> issueMovieList1 = new LinkedList<IssuedMovie>();
					issueMovieList1=listByPersonId.get(tempIssuedMovieObj.getPersonid());
					issueMovieList1.remove(tempIssuedMovieObj);
					
					if(!listByMovieId.containsKey(issuedmovie.getPersonid())) {
						LinkedList<IssuedMovie> list = new LinkedList<IssuedMovie>();
						issueMovieList1.add(issuedmovie);
						listByPersonId.put(issuedmovie.getPersonid(),list);
					}
					else
					{
						listByPersonId.get(issuedmovie.getPersonid()).add(issuedmovie);
					}
					
					listByIssuedId.remove(issuedmovie.getIssueid());
					listByIssuedId.put(issuedmovie.getIssueid(), issuedmovie);
					
					
					return result;
					
				}
				throw new IssuedmovieException("No updates are necessary.");
			}
			else
			{
				ps = con.prepareStatement("update ISSUEDMOVIE set FINE = ?  where issueId = ?");
				ps.setInt(1, issuedmovie.getFine());
				ps.setInt(2, issuedmovie.getIssueid());
				int result=ps.executeUpdate();
				if(result <= 0)
				{
					throw new IssuedmovieException("No issued movie found in the system.");
				}
				return result;
				
			}
			
	}
	

	public IssuedMovie insert(IssuedMovie issuedmovie, Connection con)
			throws IssuedmovieException, SQLException {

			PreparedStatement ps = null;
		
			ps = con.prepareStatement("insert into ISSUEDMOVIE( MOVIEID,PERSONID, ISSUEDATE, ISSUESTATUS, DUEDATE) values (?, ?, ?, ?, ?)");

			ps.setInt(1, issuedmovie.getMovieid());
			ps.setInt(2, issuedmovie.getPersonid());
			ps.setDate(3, DateConvert.convertUtilToSQLdate(issuedmovie.getIssuedate()));
			ps.setString(4, issuedmovie.getIssuedstatus());
			ps.setDate(5, DateConvert.convertUtilToSQLdate(issuedmovie.getDuedate()));
			
			int result=ps.executeUpdate();
			if(result <= 0)
			{
				throw new IssuedmovieException("Failed to insert issue movie in the system.");
			}
			
			IssuedMovie issueMovieList[] = findExecutingUserSelect("Select issueId, personId, movieId, issueDate, issueStatus, dueDate, returnDate, fine from issuedmovie WHERE movieId = ? and personId = ? and issuedate= ?",
					new Object[]{issuedmovie.getMovieid(),issuedmovie.getPersonid(),DateConvert.convertUtilToSQLdate(issuedmovie.getIssuedate())},con);
			
			listByIssuedId.put(issueMovieList[0].getIssueid(), issuedmovie);
			if(!listByPersonId.containsKey(issuedmovie.getPersonid())) {
				LinkedList<IssuedMovie> issueMovie = new LinkedList<IssuedMovie>();
				issueMovie.add(issuedmovie);
				listByPersonId.put(issuedmovie.getPersonid(), issueMovie);
			}
			else
			{
				listByPersonId.get(issuedmovie.getPersonid()).add(issuedmovie);
			}
			if(!listByMovieId.containsKey(issuedmovie.getMovieid())) {
				LinkedList<IssuedMovie> issueMovie = new LinkedList<IssuedMovie>();
				issueMovie.add(issuedmovie);
				listByMovieId.put(issuedmovie.getMovieid(), issueMovie);
			}
			else
			{
				listByMovieId.get(issuedmovie.getMovieid()).add(issuedmovie);
			}
			
			System.out.println("Success");
			return issuedmovie;
	}

	
	
	public IssuedMovie findByIssueid(int issueid, Connection con)
			throws IssuedmovieException, SQLException {
		
		// Find issued movie from the List
		// If found return the issuedMovie object
		// else check in database

		
		IssuedMovie issuedMovie=listByIssuedId.get(issueid);
		if(issuedMovie==null)
		{
			PreparedStatement stmt = null;
			ResultSet rs = null;
			String SQL_STATEMENT = "Select issueId, personId, movieId, issueDate, issueStatus, dueDate, returnDate, fine from issuedmovie where issueId = ? order by issueId";
		
			stmt = con.prepareStatement(SQL_STATEMENT);
			stmt.setInt(1, issueid);
			rs = stmt.executeQuery();
			issuedMovie = fetchSingleResult(rs);
			if(issuedMovie != null) { 
				listByIssuedId.put(issueid, issuedMovie);
				
			}
			else {
				throw new IssuedmovieException("No issued movie found the system");
			}
			
		}
			return issuedMovie;
		
	}

	public IssuedMovie[] findByPersonid(int personid, Connection con)
			throws IssuedmovieException, SQLException {
		if(listByPersonId.containsKey(personid)) {
			int size=listByPersonId.get(personid).size();
			IssuedMovie[] issuedMovieList = listByPersonId.get(personid).toArray(new IssuedMovie[size]);
			return issuedMovieList;
		}
		
		
		PreparedStatement stmt = null;
		ResultSet rs = null;
		String SQL_STATEMENT = "Select issueId, personId, movieId, issueDate, issueStatus, dueDate, returnDate, fine from issuedmovie where personId = ? order by personId";
		
			stmt = con.prepareStatement(SQL_STATEMENT);
			stmt.setInt(1, personid);
			rs = stmt.executeQuery();
			if(rs != null)
			{
				if(rs.getRow()==0)
				{
					throw new IssuedmovieException("No issued movie found the system");
				}
				return fetchMultiResults(rs);
			}
			else
			{
				throw new IssuedmovieException("No issued movie found the system");
			}
	}

	public IssuedMovie[] findCurrentByPersonid(int personid, Connection con)
			throws IssuedmovieException, SQLException {
		if(listByPersonId.containsKey(personid)) {
			int size=listByPersonId.get(personid).size();
			IssuedMovie[] issuedMovieList = listByPersonId.get(personid).toArray(new IssuedMovie[size]);
			return issuedMovieList;
		}


		PreparedStatement stmt = null;
		ResultSet rs = null;
		String SQL_STATEMENT = "Select issueId, personId, movieId, issueDate, issueStatus, dueDate, returnDate, fine from issuedmovie where personId = ? and issueStatus=CURR";

			stmt = con.prepareStatement(SQL_STATEMENT);
			stmt.setInt(1, personid);
			rs = stmt.executeQuery();
			if(rs != null)
			{
				if(rs.getRow()==0)
				{
					throw new IssuedmovieException("No issued movie found the system");
				}
				return fetchMultiResults(rs);
			}
			else
			{
				throw new IssuedmovieException("No issued movie found the system");
			}
		}
	public IssuedMovie[] findByMovieid(int movieid, Connection con)
			throws IssuedmovieException, SQLException {
		
		
		
		
		if(listByMovieId.containsKey(movieid)) {
			int size=listByMovieId.get(movieid).size();
			IssuedMovie[] issuedMovieList = listByMovieId.get(movieid).toArray(new IssuedMovie[size]);
			return issuedMovieList;
		}
		
		
		PreparedStatement stmt = null;
		ResultSet rs = null;
		String SQL_STATEMENT = "Select issueId, personId, movieId, issueDate, issueStatus, dueDate, returnDate, fine from issuedmovie where movieId = ? order by movieId";
		
			stmt = con.prepareStatement(SQL_STATEMENT);
			stmt.setInt(1, movieid);
			rs = stmt.executeQuery();
			if(rs != null)
			{
				if(rs.getRow()==0)
				{
					throw new IssuedmovieException("This movie is not yet issued");
				}
				return fetchMultiResults(rs);
			}
			else
			{
				throw new IssuedmovieException("This movie is not yet issued");
			}
	}







	protected IssuedMovie fetchSingleResult(ResultSet rs) throws SQLException {
		if (rs.next()) {
			IssuedMovie dto = new IssuedMovie();
			populateVO(dto, rs);
			return dto;
		} else {
			return null;
		}
	}

	protected void populateVO(IssuedMovie dto, ResultSet rs)
			throws SQLException {
		dto.setIssueid(rs.getInt("issueId"));
		dto.setPersonid(rs.getInt("personId"));
		dto.setMovieid(rs.getInt("movieId"));
		dto.setIssuedate(DateConvert.convertSQLToUtilDate(rs.getDate("issueDate")));
		dto.setIssuedstatus(rs.getString("issueStatus"));
		dto.setDuedate(DateConvert.convertSQLToUtilDate(rs.getDate("dueDate")));
		dto.setReturndate(rs.getDate("returnDate"));
		dto.setFine(rs.getInt("fine"));
	}

	public IssuedMovie[] findExecutingUserSelect(String selectStatement,
			Object[] sqlParams, Connection con) throws SQLException {
		PreparedStatement stmt = null;
		ResultSet rs = null;
		final String SQL_STATEMENT = selectStatement;
		
			stmt = con.prepareStatement(SQL_STATEMENT);
			for (int i = 0; i < sqlParams.length; i++) {
				stmt.setObject(i + 1, sqlParams[i]);
			}
			rs = stmt.executeQuery();
			return fetchMultiResults(rs);
		
	}

	protected IssuedMovie[] fetchMultiResults(ResultSet rs) throws SQLException {
		Collection<IssuedMovie> resultList = new ArrayList<IssuedMovie>();
		while (rs.next()) {
			IssuedMovie dto = new IssuedMovie();
			populateVO(dto, rs);
			resultList.add(dto);
		}
		IssuedMovie ret[] = new IssuedMovie[resultList.size()];
		resultList.toArray(ret);
		return ret;
	}
	

	
	
}
